/* 
 * Copyright [2018] [Alex/libo(liboms@hotmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.apidoc.scanner.help;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import com.hyts.apidoc.bean.ScanBaseObject;
import com.hyts.apidoc.scanner.filter.ClassNameFilter;
import com.hyts.apidoc.utility.PathUtils;

/** 
 * @title ScanHelper.java  
 * @package com.hyts.apidoc.scanner.help  
 * @description 扫描服务帮助类-用于处理扫描服务文件、class类信息  
 * @author libo/Alex
 * @email liboms@hotmail.com/liboware@163.com  
 * @date 2018年4月18日 
 * @version V1.0 
 */
public final class ScanHelper {

	 
     /**  
     * <p>扫描的结果集合</p> 
     * @fieldName scanClassList
     * @fieldType List<String>
     */ 
    List<String> scanClassList = new LinkedList<>();

	/***********************scan帮助类-单元操作类****start*****************************************/
	
	/**  
	 * <b>scanRecursive:递归单元操作</b>
	 * <p>递归选择文件遍历操作</p>
	 * @param filePath 当前待文件路径-主要为文件夹-文件则会出现问题，暂时不错处理
	 * @param excludePackages
	 * @return 返回java class类文件集合
	 */ 
    List<String> scanRecursive(String filePath,String[] excludePackages){
		try {
			filePath = URLDecoder.decode(filePath,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		File file = new File(filePath);
		File[] childFiles = file.listFiles(new ClassNameFilter(excludePackages));
	    for(File childFile:childFiles) {
		    if(childFile.isDirectory()) {
			    scanRecursive(childFile.getPath(),excludePackages);
		    }else {
		        scanClassList.add(childFile.getPath());
		    }
        }
        return this.scanClassList;
	}
	
	/**  
	 * <b>scanNonRecursive:非递归单元操作</b>
	 * <p>非递归选择文件遍历操作</p>
	 * @param filePath 当前待文件路径-主要为文件夹-文件则会出现问题，暂时不错处理
	 * @param excludePackages
	 * @return 返回java class类文件集合
	 */ 
	List<String> scanNonRecursive(String filePath,String[] excludePackages){
		File file = new File(filePath);
	    LinkedList<String> directoryClassList = new LinkedList<>();
	    if(file.isFile()) {
	        scanClassList.add(file.getPath());
	        return scanClassList;
	    }
		File[] childFiles = file.listFiles(new ClassNameFilter(excludePackages));
		for(File childFile:childFiles) {
		    if(childFile.isDirectory()) {
		    	directoryClassList.add(childFile.getPath());
		    }else {
		        scanClassList.add(childFile.getPath());
		    }
        }
		for(;!directoryClassList.isEmpty();) {
			File directoryPath = new File(directoryClassList.removeFirst());
			File[] childFile2 = directoryPath.listFiles(new ClassNameFilter(excludePackages));
			for(File childFile:childFile2) {
				if(childFile.isDirectory()) {
					directoryClassList.add(childFile.getPath());
				}else {
					scanClassList.add(childFile.getPath());
				}
			}
		}
	    return scanClassList;
	}
	
	
	/***********************scan帮助类-单元操作类****end*****************************************/

	/**  
	 * <b>scan2Recursive</b>
	 * <p>扫描包根据递归方案</p>
	 * @param obj
	 */ 
	public List<String> scanRecursive(ScanBaseObject obj) {
		if(Objects.nonNull(obj.packages) && obj.packages.length != 0) {
			Stream.of(obj.packages).forEach(packageName->{
				scanRecursive(PathUtils.package2FilePath(packageName),obj.excludePackages);
			});
		}
		return this.scanClassList;
	}
	
	/**  
	 * <b>scan2NotRecursive</b>
	 * <p>扫描包根据非递归方案</p>
	 */ 
	public List<String> scanNonRecursive(ScanBaseObject obj) {
		if(Objects.nonNull(obj.packages) && obj.packages.length != 0) {
			Stream.of(obj.packages).forEach(packageName->{
				scanNonRecursive(PathUtils.package2FilePath(packageName),obj.excludePackages);
			});
		}
		return this.scanClassList;
	}
	
}
